#!/usr/bin/env python

import os.path
import time
import pdb
import sys
import os

from daddyparsers import *
from lts import utils
import lts

# Cadenas para la funcion que imprime la ayuda del programa.

_msg_help_normal_mode_  = \
"""DADDY v2.0 - Diagnosability Analyzer for Distributed Discrete sYstems

Arguments:

  -s=S1,..,Sn ->  List of subsystems.
  -f=F1,..,Fm ->  List of faults.
  -c=C1,..,Ck ->  List of synchronization events.
  -h=0|...|6  ->  Heuristic type.
  -g          ->  It tells DADDY to graphic non-diagnosable systems.
  -t          ->  It tells DADDY to count the time the analysis take.
  -v          ->  It tells DADDY to run in verbose mode.
"""

_msg_help_short_mode_  = "\nType 'daddy.py -help' for help."

class DADDYError (Exception):
	"""
		Clase de excepcion para este modulo.
	"""
	pass

def _mode_0 (parsed_args):
	system = parsed_args["system"]
	fault_set = parsed_args["fault_set"]
	sync_set = parsed_args["sync_set"]
	graphic = parsed_args["graphic"]
	heuristic_level = parsed_args["heuristic_level"]
	take_time = parsed_args["time"]
	verbose = parsed_args["verbose"]
	if verbose:
		print "\nINFORMATION"
		print "-----------"
	# Condicion para el ciclo pricipal.
	decide_result = False
	if verbose:
		iter = 1 # Cuenta las iteraciones para el modo verbose=True.
	while not decide_result:
		# Chequeo el tipo de sincronizacion.
		sync_type = utils.check_sync_type(system, sync_set)
		# Numero de iteracion.
		if verbose:
			print "\nIteration:", iter
		# Cantidad de subsistemas.
		if verbose:
			print "\nNumber of subsystems: ", len(system)
		# Tipo de sincronizacion en esta iteracion.
		if verbose:
			if sync_type == utils.SYNC_EMPTY:
				print "Synchronization type:  EMPTY"
			elif sync_type == utils.SYNC_PARTIAL:
				print "Synchronization type:  PARTIAL"
			else:
				print "Synchronization type:  FULL"
		if verbose:
			iter += 1
		# Dice si todos los subsistemas son diagnosticables.
		all_subsystems_diag = True
		# Almacena los resultados de los subsistemas no diagnosticables.
		all_nondiag_subsystems = []
		# Chequeo la diagnosticabilidad de los subsistemas.
		for subsystem in system:
			# - DBG -
			#lts.to_file(subsystem)
			#lts.to_file(subsystem.get_twinplant())
			# - DBG -
			subsystem.isdiag = None
			if verbose:
				print "\nChecking diagnosability for:", subsystem.name
			if take_time:
				t1 = time.time()
			diag_res = subsystem.is_diagnosable(fault_set,verbose)
			if take_time:
				t2 = time.time()
			if verbose:
				if diag_res['is_diag']:
					print "It's diagnosable!"
				else:
					print "It's non-diagnosable!"
				if take_time:
					print "It takes",utils.str_time(t2-t1)
			subsystem.isdiag = diag_res['is_diag']
			all_subsystems_diag &= diag_res['is_diag']
			if not diag_res['is_diag']:
				all_nondiag_subsystems.append((subsystem,diag_res))
		# Chequeo si puedo decidir la diagnosticabilidad del sistema.
		if len(system) == 1: # Si hay un subsistema es facil.
			decide_result = True
			if all_subsystems_diag:
				print "\nRESULT"
				print "------"
				print "\nThe system is diagnosable."
			else:
				(subsystem,diag_res) = all_nondiag_subsystems[0]
				print "\nRESULT"
				print "------"
				print "\nThe system is non-diagnosable."
				utils.show_nondiag_info(subsystem, diag_res, graphic)
		elif (sync_type==utils.SYNC_EMPTY) and not all_subsystems_diag:
			# El sistema no es diagnosticable.
			decide_result = True
			print "\nRESULT"
			print "------"
			print "\nThe system is non-diagnosable because the " + \
				  "synchronization type"
			print "is EMPTY and there exist at least one non-diagnosable " + \
				  "subsystem."
			for (subsystem,diag_res) in all_nondiag_subsystems:
				utils.show_nondiag_info(subsystem, diag_res, graphic)
				print ''
		else:
			# No puedo decidir y hay mas de un sistema. Tengo que sincronizar.
			system = utils.synchronize(system,sync_set,heuristic_level,verbose)

def _print_help (mode='normal'):
	if mode == 'normal':
		print _msg_help_normal_mode_
	else:
		print _msg_help_short_mode_

if __name__ == '__main__':
	# Parseo los argumentos de entrada.
	try:
		parsed_args = parse(sys.argv[1:],1,8)
	except ParserError, (msg):
		print msg
		_print_help('short')
		sys.exit(0)
	if parsed_args["help"]:
		_print_help()
		sys.exit(0)
	if not parsed_args["fault_set"]:
		print "\nWarning! The fault list is empty. There will be no checking!"
	else:
		take_time = parsed_args["time"]
		mode = parsed_args["mode"]
		# Para contar el tiempo global.
		if take_time:
			gt1 = time.time()
		# Ejecuto el modo indicado.
		if mode == 0:
			_mode_0(parsed_args)
		else:
			# En el futuro habra mas modos.
			pass
		# Para contar el tiempo global.
		if take_time:
			gt2 = time.time()
		if take_time:
			print "\nTotal time:",utils.str_time(gt2-gt1),"\n"
